package cliente.controle;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.swing.DefaultListModel;

import cliente.modelo.Conta;
import cliente.modelo.TipoConta;
import cliente.modelo.TipoEstilo;

public class ContaControlador {

	// Ações para controlar Views

	public static void atualizaDadosEmCampoContas(
			DefaultListModel campoContasConteudo) throws SQLException,
			IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		ArrayList<Conta> todasContas = getAll(sistema.getAtualId());
		// Os clears ajudarão a atualizar a view
		campoContasConteudo.clear();

		for (int i = 0; i < todasContas.size(); i++) {
			campoContasConteudo.addElement(todasContas.get(i));
		}
	}

	// Ações de banco de dados

	public static void cria(int clienteId, TipoConta tipoDeConta, int reais,
			int centavos, TipoEstilo estiloDeConta) throws SQLException {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("cria");
		sistema.escreveServidor(clienteId);
		sistema
				.escreveServidor((tipoDeConta == TipoConta.CORRENTE) ? "CORRENTE"
						: "POUPANCA");
		sistema.escreveServidor(reais);
		sistema.escreveServidor(centavos);
		sistema
				.escreveServidor((estiloDeConta == TipoEstilo.SIMPLES) ? "SIMPLES"
						: "ESPECIAL");
	}

	// Esse cria adivinha qual o tipo de conta seria melhor para o cliente
	public static void cria(int clienteId, TipoConta tipoDeConta, int reais,
			int centavos) throws SQLException {
		TipoEstilo estiloDeConta;
		Sistema sistema = Sistema.getUnicaInstancia();
		if (reais <= sistema.getValorMinimo()) {
			estiloDeConta = TipoEstilo.SIMPLES;
		} else {
			estiloDeConta = TipoEstilo.ESPECIAL;
		}
		cria(clienteId, tipoDeConta, reais, centavos, estiloDeConta);
	}

	public static void atualiza(int id, int clienteId, TipoConta tipoDeConta,
			int reais, int centavos, TipoEstilo estiloDeConta)
			throws SQLException {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("atualiza");
		sistema.escreveServidor(id);
		sistema.escreveServidor(clienteId);
		sistema
				.escreveServidor((tipoDeConta == TipoConta.CORRENTE) ? "CORRENTE"
						: "POUPANCA");
		sistema
				.escreveServidor((estiloDeConta == TipoEstilo.SIMPLES) ? "SIMPLES"
						: "ESPECIAL");
	}

	public static void depositar(int reais, int centavos, int contaId) {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("depositar");
		sistema.escreveServidor(reais);
		sistema.escreveServidor(centavos);
		sistema.escreveServidor(contaId);
	}

	public static void sacar(int reais, int centavos, int contaId) {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("sacar");
		sistema.escreveServidor(reais);
		sistema.escreveServidor(centavos);
		sistema.escreveServidor(contaId);
	}

	public static void transferir(int reais, int centavos, int contaOrigemId,
			int contaDestinoId) {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("transferir");
		sistema.escreveServidor(reais);
		sistema.escreveServidor(centavos);
		sistema.escreveServidor(contaOrigemId);
		sistema.escreveServidor(contaDestinoId);
	}

	public static boolean validaDadosConta(String valor) {
		return Validador.validaDinheiro(valor);
	}

	public static boolean validaDadosConta(String valor, String conta) {
		return validaDadosConta(valor) && Validador.validaConta(conta);
	}

	private static Conta getConta(Sistema sistema) throws IOException {
		// retorna um cliente pegando os seus dados do servidor

		String param = sistema.getLineServidor(); // verifica que o servidor não
		// retornou a string "null"
		if (param == "null")
			return null;

		int id = Integer.parseInt(param);
		int reais = Integer.parseInt(sistema.getLineServidor());
		int centavos = Integer.parseInt(sistema.getLineServidor());
		TipoConta tipoDeConta = (sistema.getLineServidor().equalsIgnoreCase(
				"CORRENTE") ? TipoConta.CORRENTE : TipoConta.POUPANCA);
		TipoEstilo estiloDeConta = (sistema.getLineServidor().equalsIgnoreCase(
				"SIMPLES") ? TipoEstilo.SIMPLES : TipoEstilo.ESPECIAL);
		int clienteId = Integer.parseInt(sistema.getLineServidor());

		return new Conta(id, reais, centavos, tipoDeConta, estiloDeConta,
				clienteId);
	}

	private static Conta getConta(Sistema sistema, int id) throws IOException {
		// retorna um cliente pegando os seus dados do servidor
		int reais = Integer.parseInt(sistema.getLineServidor());
		int centavos = Integer.parseInt(sistema.getLineServidor());
		TipoConta tipoDeConta = (sistema.getLineServidor().equalsIgnoreCase(
				"CORRENTE") ? TipoConta.CORRENTE : TipoConta.POUPANCA);
		TipoEstilo estiloDeConta = (sistema.getLineServidor().equalsIgnoreCase(
				"SIMPLES") ? TipoEstilo.SIMPLES : TipoEstilo.ESPECIAL);
		int clienteId = Integer.parseInt(sistema.getLineServidor());

		return new Conta(id, reais, centavos, tipoDeConta, estiloDeConta,
				clienteId);
	}

	public static boolean exists(int clienteId) {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("exists");
		sistema.escreveServidor(clienteId);
		try {
			return sistema.getLineServidor().equalsIgnoreCase("true"); // se for
			// igual
			// a
			// "true"
			// retornará
			// true
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}

	public static Conta get(int id) throws IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("get");
		sistema.escreveServidor(id);
		return getConta(sistema);
	}

	public static ArrayList<Conta> getCorrente(int clienteId)
			throws IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("get");
		sistema.escreveServidor("corrente");
		sistema.escreveServidor(clienteId);
		String param;
		ArrayList<Conta> contas = new ArrayList<Conta>();
		while (!(param = sistema.getLineServidor()).equalsIgnoreCase("END")) {
			int id = Integer.parseInt(param);
			contas.add(getConta(sistema, id));
		}
		return contas;
	}

	public static ArrayList<Conta> getPoupança(int clienteId)
			throws IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("get");
		sistema.escreveServidor("poupanca");
		sistema.escreveServidor(clienteId);
		String param;
		ArrayList<Conta> contas = new ArrayList<Conta>();
		while (!(param = sistema.getLineServidor()).equalsIgnoreCase("END")) {
			int id = Integer.parseInt(param);
			contas.add(getConta(sistema, id));
		}
		return contas;
	}

	public static ArrayList<Conta> getAll() throws NumberFormatException,
			IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.getAll que está no servidor,
		// escrevendo por socket os parâmetros
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("getAll");
		String param;
		ArrayList<Conta> contas = new ArrayList<Conta>();
		while (!(param = sistema.getLineServidor()).equalsIgnoreCase("END")) {
			int id = Integer.parseInt(param);
			contas.add(getConta(sistema, id));
		}
		return contas;
	}

	public static ArrayList<Conta> getAll(int clienteId)
			throws NumberFormatException, IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.getAll que está no servidor,
		// escrevendo por socket os parâmetros
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("getAll");
		sistema.escreveServidor(clienteId);
		String param;
		ArrayList<Conta> contas = new ArrayList<Conta>();
		while (!(param = sistema.getLineServidor()).equalsIgnoreCase("END")) {
			int id = Integer.parseInt(param);
			contas.add(getConta(sistema, id));
		}
		return contas;
	}

	public static void delete(int id) {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.delete que está no servidor,
		// escrevendo por socket os parâmetros
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("delete");
		sistema.escreveServidor(id);
	}

	public static void deleteConta(int id, DefaultListModel campoContasConteudo)
			throws SQLException, IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.delete que está no servidor,
		// escrevendo por socket os parâmetros
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("delete");
		sistema.escreveServidor(id);
		ContaControlador.atualizaDadosEmCampoContas(campoContasConteudo);
	}

	public static boolean contaExists(int id) {
		Sistema sistema = Sistema.getUnicaInstancia();
		sistema.escreveServidor("ContaControlador");
		sistema.escreveServidor("exists");
		sistema.escreveServidor("conta");
		sistema.escreveServidor(id);
		try {
			return sistema.getLineServidor().equalsIgnoreCase("true"); // se for
			// igual
			// a
			// "true"
			// retornará
			// true
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}

	public static String getSaldo(Conta conta) {
		return getSaldo(conta.getReais(), conta.getCentavos());
	}

	public static String getSaldo(int reais, int centavos) {
		if (centavos < 0) {
			centavos *= -1;
		}
		return String.format("R$ %d,%02d", reais, centavos);
	}

	public static boolean podeSacarPoupanca(Conta conta, int reais, int centavos) {
		Sistema sistema = Sistema.getUnicaInstancia();
		int dinheiro = conta.getReais() * 100 + conta.getCentavos();
		dinheiro -= reais * 100 + centavos;
		if (conta.getEstiloDeConta() == TipoEstilo.ESPECIAL) {
			dinheiro -= (sistema.getMovimentacaoEspecialReais() * 100 + sistema
					.getMovimentacaoEspecialCentavos());
		} else {
			dinheiro -= (sistema.getMovimentacaoSimplesReais() * 100 + sistema
					.getMovimentacaoSimplesCentavos());
		}
		dinheiro -= sistema.getImpostos() * (reais * 100 + centavos);
		return (dinheiro >= 0);
	}
}
